CircleCI上でCode 1で失敗扱いになるのはpipefailのせいかもしれない
https://gyazo.com/b0a60e896f3280d8f2612957bb8d271d
php artisan code:analyse --env=testingでも同様の結果になる
原因
対応
code:config.yml
- run:
name: Run reviewdog
shell: /bin/sh # 何の設定もしていないシェルを指定してあげればいい
状況(試行錯誤)
SSHで同様のコマンドを叩いても終了ステータスは0
code:zsh
circleci:~/laravel$ php artisan code:analyse --env=testing --paths="packa
ges" --error-format raw --no-progress --level=7 --no-tty 2>&1 | ./reviewdog -f=phpstan
-reporter=github-pr-review
circleci:~/laravel$ echo $?
0
上はLarastanだが、PHPStanでも同様のことが起きた
VM上で、pipeでつないだコマンドを確認
code:zsh
$ ./vendor/bin/phpstan analyze --level=5 -c phpstan.neon --error-format raw --no-progress packages | ./reviewdog -f=phpstan -reporter=github-pr-review
# PHPStanの出力たくさん
$ echo $?
1
前半のみの場合も見ていく
code:zsh
# PHPStanのみの場合
$ ./vendor/bin/phpstan analyze --level=5 -c phpstan.neon --no-progress --error-format raw packages/
# PHPStanの出力たくさん
$ echo $?
1
# pipeでつなぐ
$ ./vendor/bin/phpstan analyze --level=5 -c phpstan.neon --no-progress --error-format raw packages/ | ./reviewdog -f=phpstan --diff="git diff"
# PHPStanでなにもでない場合
$ echo $?
0
# diffが出る(=PHPStanで検知されている)場合
$ echo $?
0
PHPStanの出力がある場合、単体の実行であれば1になっているが、pipeでつなげると0で怪しい
調べると、pipefailを使うと、pipeでつないだコマンドが途中で失敗した場合に、そこで実行を止めることができることがわかった pipefailを使っていない場合、最後のコマンドが正常終了ならecho $?は0になる。今回の場合、reviewdogは正常終了しているので0を返す
整理すると
ローカルではpipefailがついていないので、最後のコマンドの結果が返る
CircleCIのコマンド実行は、デフォルトで-eo pipefailがついているので、pipeする前のコマンド実行が0以外を出力したら止まる(=PHPStanが何か違反を検知したら止まる)
CI的にはコマンドが失敗したらテストをすぐに落としてほしいのでpipefailがデフォルトなのは自然
PHPStan的にはエラーを発見しているので異常な状態であり、Exit Code 1で終了するのは自然
reviewdogはすべてのエラーの中からPR中のエラーの差分を教えてくれるので、PHPStan側でエラーを出させてその出力結果を受取ることを期待している